'''
Description: 
Author: Zilu
Date: 2021-11-06 17:16:55
Version: 
LastEditTime: 2021-11-06 18:45:10
LastEditors: Zilu
'''
# 函数对象可以作为函数的返回值
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax += n
        return ax
    return sum

f = lazy_sum(1, 2, 3, 4, 5, 6)
f
f()

# lazy_sum返回sum时，相关参数和变量都保存在返回的函数对象中，这称为“闭包”
def list_test():
    L = []
    for i in range(0,3):
        L.append(i)
    return L

a,b,c=list_test()

def count():
    fs=[]
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1,f2,f3 = count()
f1(),f2(),f3()
# 上面的函数值都是9，因为返回的f函数中引用了变量i，最后结束的时候i的值为3，三个函数引用的i都变成了3
# 返回闭包时牢记一点：返回函数不要引用任何循环变量，或者后续会发生变化的变量。
# 或者可以使用另外一个函数绑定当前循环的参数，但是这样代码比较长，比较难读

# 练习：利用闭包返回一个计数器函数，每次调用它返回递增整数
def createCounter():
    n = 0
    def counter():
        nonlocal n
        n += 1
        return n
    return counter
# 不能直接使用普通变量，会报错未声明，因为内部函数不能改变外部函数中变量的引用

counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA())



